package com.fc.advbox.process.migrate.dialects;

import com.fc.advbox.process.migrate.Dialect;
import com.fc.advbox.process.migrate.Migrator;

import static java.lang.String.format;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


/**
 * abstract dialects which implements the most common means to implement the various interfaces.
 * 
 * @author Chris
 */
public abstract class AbstractDialect implements Dialect {
 
    /**
     * @see Dialect#createVersionTable(Connection, String)
     */
    @Override public void createVersionTable(Connection conn, String versionTable) throws SQLException {
        executeSql(conn, format( "CREATE TABLE %s(%s INT)", versionTable, VERSION_COLUMN_NAME) );
        executeSql(conn, format( "INSERT INTO %s VALUES(0)", versionTable ) );
        if(!conn.getAutoCommit()) {
            conn.commit();
        }
    }

    /**
     * @see Dialect#executeSql(Connection, String)
     */
    @Override public void executeSql(Connection conn, String sql) throws SQLException {
        Statement ps = conn.createStatement();
        if ( sql.length() > Migrator.SQL_LENGTH_LIMIT ) {
            throw new SQLException("SQL is too long: Allowed Length: [" + Migrator.SQL_LENGTH_LIMIT + "] Actual Length: [" + sql.length() + "]");
        } else {
            ps.executeQuery(sql);
        }
        ps.close();
    }
    
    /**
     * @see Dialect#getVersion(Connection, String)
     */
    @Override public int getVersion(Connection conn, String versionTable) throws SQLException {
        PreparedStatement ps = conn.prepareStatement(format("SELECT * FROM %s", versionTable));
        ResultSet results = ps.executeQuery();
        
        if (results.next()) {
            int version = results.getInt(1);
            
            if (results.next()) {
                throw new SQLException( format("more than one entry existed in the %s table", versionTable) );
            }
            return version;
        } else {
            throw new SQLException( format("no rows found in the %s table", versionTable));
        }
    }
    
    
    /**
     * @see Dialect#setVersion(Connection, int, String)
     */
    @Override public void setVersion(Connection conn, int version, String versionTable) throws SQLException {
        executeSql( conn, format( "UPDATE %s SET %s = %s", versionTable, VERSION_COLUMN_NAME, version) );
    }

}
